﻿using System;
using System.Linq;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.ComponentModel;

namespace PerfAnalyzerLib
{
	public class Argument<T> : IArgument
	{
		private string _name;
		private bool _isFlag;
		private bool _allowMultiple;
		private bool _isMandatory;
		private List<T> _values = new List<T>();

		/// <summary>
		/// Argument name.
		/// </summary>
		public string Name
		{ 
			get
			{
				return _name;
			}
			
			set
			{
				_name = value.ToLower();
			}
		}

		/// <summary>
		/// Other alternatives for names.
		/// </summary>
		public List<string> AlternativeNames { get; set; }

		/// <summary>
		/// Argument Description.
		/// </summary>
		public string Description { get; set; }

		/// <summary>
		/// Is the argument a flag.
		/// </summary>
		public bool IsFlag
		{
			get
			{
				return _isFlag;
			}
			set
			{
				_isFlag = value;
				CheckPropertiesCompatibility();
			}
		}

		/// <summary>
		/// Is the argument a flag.
		/// </summary>
		public bool AllowMultiple
		{
			get
			{
				return _allowMultiple;
			}
			set
			{
				_allowMultiple = value;
				CheckPropertiesCompatibility();
			}
		}

		/// <summary>
		/// Is the argument mandatory.
		/// </summary>
		public bool IsMandatory 
		{
			get
			{
				return _isMandatory;
			}
			set
			{
				_isMandatory = value;
				CheckPropertiesCompatibility();
			}
		}

		public bool IsPresent { get; protected set; }

		public ReadOnlyCollection<T> Values { get { return _values.AsReadOnly(); } }

		public T Value
		{
			get
			{
				if (_allowMultiple)
					throw new Exception();

				if (!_values.Any())
					throw new Exception();

				return _values[0];
			}
		}

		/// <summary>
		/// Constructor.
		/// </summary>
		/// <param name="name">Argument name.</param>
		/// <param name="isMandatory">Is parameter mandatroy?</param>
		/// <param name="description">Argument description.</param>
		public Argument(string name, string description, bool isMandatory = false, bool isFlag = false, bool allowMultiple = false)
		{
			Name = name;
			Description = description;
			IsMandatory = isMandatory;
			AllowMultiple = allowMultiple;

			AlternativeNames = new List<string>();
			IsPresent = false;
			CheckPropertiesCompatibility();

			IsFlag = isFlag;
		}

		private void CheckPropertiesCompatibility()
		{
			if (_isFlag && (_isMandatory || _allowMultiple))
				throw new Exception();
		}

		public void AddValue(string value)
		{
			if (IsPresent && !AllowMultiple)
			{
				// throw error because should be unique
				throw new Exception();
			}

			TypeConverter converter = TypeDescriptor.GetConverter(typeof(T));
			_values.Add((T)converter.ConvertFrom(value));
			IsPresent = true;
		}
	}
}
